﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.MountAndBlade.CoreManaged
// Assembly: TaleWorlds.MountAndBlade, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: D5209D1B-76B5-47CA-B957-255CD4B2CE6B
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.MountAndBlade.dll

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using TaleWorlds.DotNet;
using TaleWorlds.Library;

#nullable disable
namespace TaleWorlds.MountAndBlade
{
  public class CoreManaged : IManagedComponent
  {
    private static CoreManaged _instance;
    private static ICallbackManager _callbackManager;
    private static readonly Dictionary<int, IntPtr> _engineApiPointers = new Dictionary<int, IntPtr>();
    private static Delegate _passManagedCoreCallbackMethodPointersMono = (Delegate) null;

    public string ManagedCallbacksDll
    {
      get => ManagedDllFolder.Name + "TaleWorlds.MountAndBlade.AutoGenerated.dll";
    }

    public CoreManaged() => CoreManaged._instance = this;

    [MBCallback]
    public static void Start()
    {
      Managed.Start((IEnumerable<IManagedComponent>) new IManagedComponent[0]);
    }

    void IManagedComponent.OnStart()
    {
      Debug.DebugManager = (IDebugManager) new MBDebugManager();
      Dictionary<string, System.Type> dictionary = new Dictionary<string, System.Type>();
      foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
      {
        Dictionary<string, System.Type> second = this.CollectModuleAssemblyTypes(assembly);
        dictionary = dictionary.Union<KeyValuePair<string, System.Type>>((IEnumerable<KeyValuePair<string, System.Type>>) second).ToDictionary<KeyValuePair<string, System.Type>, string, System.Type>((Func<KeyValuePair<string, System.Type>, string>) (k => k.Key), (Func<KeyValuePair<string, System.Type>, System.Type>) (v => v.Value));
      }
      Managed.InitializeTypes(dictionary);
    }

    private Dictionary<string, System.Type> CollectModuleAssemblyTypes(Assembly moduleAssembly)
    {
      Dictionary<string, System.Type> dictionary = new Dictionary<string, System.Type>();
      try
      {
        foreach (System.Type type in moduleAssembly.GetTypes())
        {
          if (typeof (ManagedObject).IsAssignableFrom(type) || typeof (DotNetObject).IsAssignableFrom(type))
            dictionary.Add(type.Name, type);
        }
      }
      catch (Exception ex)
      {
        dictionary.Clear();
      }
      return dictionary;
    }

    [MBCallback]
    internal static void OnLoadCommonFinished() => FaceGen.CreateInstance();

    private void OnInitialize()
    {
      List<System.Type> typesSafe = AssemblyLoader.LoadFrom(this.ManagedCallbacksDll).GetTypesSafe();
      System.Type type1 = (System.Type) null;
      foreach (System.Type type2 in typesSafe)
      {
        if (((IEnumerable<System.Type>) type2.GetInterfaces()).Contains<System.Type>(typeof (ICallbackManager)))
        {
          type1 = type2;
          break;
        }
      }
      CoreManaged._callbackManager = type1.GetConstructor(new System.Type[0]).Invoke(new object[0]) as ICallbackManager;
      CoreManaged._callbackManager.Initialize();
      Delegate[] delegates = CoreManaged._callbackManager.GetDelegates();
      for (int index = 0; index < delegates.Length; ++index)
      {
        try
        {
          CoreManaged.PassManagedCoreCallbackMethodPointers(delegates[index]);
        }
        catch (Exception ex)
        {
          CoreManaged.PassManagedCoreCallbackMethodPointers((Delegate) null);
          // ISSUE: variable of a boxed type
          __Boxed<int> local = (ValueType) index;
          Console.WriteLine(ex.ToString() + " " + (object) local);
        }
      }
      MBAPI.SetObjects(CoreManaged._callbackManager.GetScriptingInterfaceObjects());
      Module.CreateModule();
    }

    void IManagedComponent.OnCustomCallbackMethodPassed(string name, Delegate method)
    {
      if (!(name == "MBCore"))
        return;
      CoreManaged._passManagedCoreCallbackMethodPointersMono = method;
      this.OnInitialize();
    }

    [MBCallback]
    internal static void Finalize()
    {
      Module.FinalizeCurrentModule();
      Common.MemoryCleanupGC();
    }

    void IManagedComponent.OnApplicationTick(float dt)
    {
      Module.CurrentModule.OnApplicationTick(dt);
    }

    [MBCallback]
    internal static void CheckSharedStructureSizes()
    {
      CoreManaged._callbackManager.CheckSharedStructureSizes();
    }

    [MBCallback]
    internal static void EngineApiMethodInterfaceInitializer(int id, IntPtr pointer)
    {
      CoreManaged._engineApiPointers.Add(id, pointer);
    }

    [MBCallback]
    internal static void FillEngineApiPointers()
    {
      foreach (KeyValuePair<int, IntPtr> engineApiPointer in CoreManaged._engineApiPointers)
      {
        try
        {
          CoreManaged._callbackManager.SetFunctionPointer(engineApiPointer.Key, engineApiPointer.Value);
        }
        catch (Exception ex)
        {
          Console.WriteLine("error: " + (object) engineApiPointer.Key + " " + (object) ex);
        }
      }
    }

    private static void PassManagedCoreCallbackMethodPointers(Delegate methodDelegate)
    {
      CoreManaged._passManagedCoreCallbackMethodPointersMono?.DynamicInvoke((object) methodDelegate);
    }
  }
}
